A software developer uses a variety of tools and techniques to facilitate the development process. Among the tools the software developer uses are source-level debuggers, which help the developer determine the origin of any bugs or errors in the source code of the program. Certain source-level debuggers provide a feature known as "Edit and Continue." Edit and Continue allows the developer to stop a program during mid-execution, edit the source code and continue executing the program with the edits in effect. Edit and Continue is provided, for example, in the QuickBASIC.TM. 4.0 interpreted programming environment sold by Microsoft Corporation (Redmond, Wash.), and in the Visual Basics.TM. 3.0 interpreted programming environment from Microsoft Corporation.
In general, debuggers restrict the kinds of edits that can be made using the Edit and Continue feature. Program changes that cannot be made compatibly with Edit and Continue are referred to as "rude edits." A developer faced with a rude edit can either make the edit and not continue program execution, or can forego edit and continue. The fewer rude edits a debugger has, the more flexible and useful the debugger is.
Developers commonly use the Edit and Continue feature to add a new local variable to a procedure of a program. Typically, variables that are local to a procedure are stored on a stack in a stack frame. A stack is a last-in-first-out (LIFO) structure that allows a processor to place, or "push," data onto it, thus burying any data already present in the stack beneath the most recently pushed data. Thereafter, the processor can retrieve, or "pop," data from the stack in a LIFO fashion. As an item is removed from the top of the stack, the item buried beneath it rises to the top of the stack. Items stored in the stack can be atomic data items or stack frames containing collections of related data. For purposes of this description, a stack frame (or, more simply, a "frame") refers to a contiguous portion of a stack that contains a collection of information (such as variable values) associated with a particular procedure of a program. Typically, a procedure has one or more stack frames associated with it. It is convenient to speak of the stack frame that is positioned uppermost in the stack as being on "top" of the stack, and to speak of a stack frame located beneath another stack frame as being "buried" in the stack below the top of the stack. A stack pointer is typically maintained to indicate the current address of the top of the stack. The stack pointer is often stored in memory or in a dedicated register.
Each stack frame is at any given time in one of three states:
1. Not present in the stack. A procedure's stack frame is created when the procedure begins to execute, and is removed from the stack when the procedure is finished executing. Thus, if the procedure is neither actively executing nor in a state of suspended execution, it has no stack frame in the stack.
2. On top of the stack. The stack frame for the procedure that is currently executing is on top of the stack.
3. Buried in the stack. When, during execution, a first procedure calls or is interrupted by a second procedure (or by another invocation of the first procedure, as in a recursive subroutine call), the stack frame of the first procedure is buried by the creation of the stack frame of the second procedure. That is, a new stack frame for the called or interrupting procedure is created and is pushed onto the stack, thus bringing the stack frame of the calling or interrupted procedure below the top of the stack. Once the second procedure is finished executing, its stack frame is removed from the stack and the stack frame of the first procedure is thus returned to the top of the stack.
Known Edit and Continue facilities allow developers to add local variables to a procedure when that procedure's stack frame is in either of the first two states. If the stack frame is currently not present (i.e., the first state), a new variable or variables can easily be added by allocating the necessary additional space at such time as the stack frame is created. If the stack frame is on top of the stack (i.e., the second state), the necessary additional space is allocated and the stack pointer is adjusted accordingly. However, when the stack frame is buried in the stack,there is no room for it to grow without affecting the rest of the stack.
It is not practical to grow buried stack frames in place. This would require moving other stack frames to avoid destructively overwriting them. When a stack frame is added to the stack, however, references to it (in its current position) are created in potentially countless and unknown places. If the stack frame were moved, these references would be wrong and the system would fail. The system has no method of tracking or finding these references to update them all. Thus known Edit and Continue facilities treat any attempt to add local variables to a procedure with a stack frame that is buried below the top of the stack as a rude edit. In particular, a developer cannot add a local variable to a procedure that either directly or indirectly calls the currently active procedure with a frame that is on top of the stack.
A related problem arises with regard to local "temporaries," (i.e., temporary storage locations used for intermediate calculations local to particular procedures). Temporaries behave like local variables but do not appear explicitly in the source code. A developer attempting to Edit and Continue a program can unwittingly request a program modification that requires adding a new temporary to a procedure and, hence, requires growing the stack frame for the procedure. If the procedure has no stack frame or if its stack frame is on top of the stack, the modification is allowed by known Edit and Continue facilities. However, if the procedure has a buried stack frame, the modification is treated as a rude edit. This seemingly inconsistent behavior can lead to confusion and frustration on the developer's part, because the developer does not know why some edits are allowed and other apparently similar edits are refused.